package com.iwhalecloud.bss.kite.cucc.service.scene.query;

import com.google.common.collect.Lists;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQueryFifthGenerationService;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneAdditionalOfferInstService;
import com.iwhalecloud.bss.kite.client.dto.DataResult;
import com.iwhalecloud.bss.kite.client.dto.inst.AdditionalOfferGroupDTO;
import com.iwhalecloud.bss.kite.client.dto.inst.InstAttrDTO;
import com.iwhalecloud.bss.kite.client.dto.inst.OfferInstDTO;
import com.iwhalecloud.bss.kite.client.dto.inst.ProdInstDTO;
import com.iwhalecloud.bss.kite.client.dto.spec.MemberRightOfferDTO;
import com.iwhalecloud.bss.kite.client.dto.spec.OfferDTO;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.validate.annotation.KiteNotBlank;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferRelCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ProductCache;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.OfferRelInfo;
import com.iwhalecloud.bss.kite.dataservice.mapper.spec.OfferGrpMemberMapper;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.service.scene.attr.OperateInstAttrService;
import com.iwhalecloud.bss.kite.service.util.CopyToDtoUtil;
import com.ztesoft.bss.order.cpc.dto.offergrp.OfferGrpMember;
import com.ztesoft.bss.provinces.chongqing.utils.StrTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author G
 * @since 2019/6/11
 */
@Service("querySceneAdditionalOfferInstService")
public class QuerySceneAdditionalOfferInstService extends QuerySceneOfferInstService implements IQuerySceneAdditionalOfferInstService {

    @Autowired
    private IQuerySceneInstService querySceneInstService;

    @Autowired
    private OperateInstAttrService operateInstAttrService;

    @Autowired
    private IQueryFifthGenerationService queryFifthGenerationService;

    @Autowired
    private OfferGrpMemberMapper offerGrpMemberMapper;

    /***
     * 获取套餐销售品实例的所有可选包销售品实例
     *
     * @param sceneInstId
     * @param mainOfferInstId
     * @param custId 客户id，分片字段，必填
     * @return
     */
    @Override
    @Validated
    public DataResult<List<OfferInstDTO>> listAdditionalOfferInstsForOfferInst(@KiteNotBlank String sceneInstId,
                                                                               @KiteNotBlank String mainOfferInstId, @KiteNotBlank String custId) {
        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listAdditionalOfferInstsFromMainOfferInst(custId,
            mainOfferInstId);
        List<OfferInstDTO> dtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(kiteOfferInstList)) {
            dtoList = CopyToDtoUtil.transOfferInstDtoList(kiteOfferInstList);
            // TODO 待确认 装箱
        }
        // else {
        // dtoList = queryAdditionalOfferInstBO.listAdditionalOfferInstByOfferInstId(mainOfferInstId, custId);
        // checkAndPutOfferInstList(dtoList, queryAdditionalOfferInstBO);
        // }
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }

    /***
     * 获取接入产品实例的所有可选包销售品实例
     *
     * @param sceneInstId
     * @param accessProdInstId
     * @param custId 客户id，分片字段，必填
     * @return
     */
    @Override
    @Validated
    public DataResult<List<OfferInstDTO>> listAdditionalOfferInstsForAccessProdInst(@KiteNotBlank String sceneInstId,
        @KiteNotBlank String accessProdInstId, @KiteNotBlank String custId) {
        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listAdditionalOfferInstsFromProdInst(custId,
            accessProdInstId);
        List<OfferInstDTO> dtoList = new ArrayList<>(0);
        if (!CollectionUtils.isEmpty(kiteOfferInstList)) {
            dtoList = CopyToDtoUtil.transOfferInstDtoList(kiteOfferInstList);
            // TODO 待确认 装箱
        }
        // else {
        // dtoList = queryAdditionalOfferInstBO.listAdditionalOfferInstByProdInstId(accessProdInstId, custId);
        // checkAndPutOfferInstList(dtoList, queryAdditionalOfferInstBO);
        // }
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }

    /***
     * 获取可选包销售品实例(包含以下两种情况)<br>
     * 1、接入产品实例下的可选包销售品实例<br>
     * 2、接入产品实例所属的套餐销售品实例下包含此接入产品实例明细的可选包销售品实例
     *
     * @param sceneInstId
     * @param prodInstId
     * @param custId 客户id，分片字段，必填
     * @return
     */
    @Override
    @Validated
    public DataResult<List<OfferInstDTO>> listAdditionalOfferInstsByProdInstId(@KiteNotBlank String sceneInstId,
        @KiteNotBlank String prodInstId, @KiteNotBlank String custId) {
//        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listAdditionalOfferInstsByProdInstId(custId, prodInstId);
        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listOfferInstsByProdInstId(custId, prodInstId, Arrays.asList(InstType.ADDITIONAL_OFFER_INST));
        List<OfferInstDTO> dtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(kiteOfferInstList)) {
            dtoList = CopyToDtoUtil.transOfferInstDtoList(kiteOfferInstList);
            // TODO 待确认 装箱
        }
        // else {
        // dtoList = queryAdditionalOfferInstBO.listAllAdditionalOfferInstByProdInstId(prodInstId, custId);
        // checkAndPutOfferInstList(dtoList, queryAdditionalOfferInstBO);
        // }
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }

    /**
     * 获取可选包销售品实例(在用，状态不为D)
     *
     * @param sceneInstId
     * @param prodInstId
     * @param custId
     * @return
     */
    @Override
    @Validated
    public DataResult<List<OfferInstDTO>> listAdditionalOfferInstsInUseByProdInstId(@KiteNotBlank String sceneInstId,
                                                                                    @KiteNotBlank String prodInstId, @KiteNotBlank String custId) {
        //        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listAdditionalOfferInstsByProdInstId(custId, prodInstId);
//        List<KiteOfferInst> kiteOfferInstList = querySceneInstService
//            .listOfferInstsByProdInstId(custId, prodInstId, Arrays.asList(InstType.ADDITIONAL_OFFER_INST));
        //将明细为D的过滤掉
        List<KiteOfferInst> kiteOfferInstList = querySceneInstService
                .listOfferInstsByProdInstId(custId, prodInstId, Arrays.asList(InstType.ADDITIONAL_OFFER_INST),
                        Lists.newArrayList(ActionType.A, ActionType.K, ActionType.M));
        List<OfferInstDTO> dtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(kiteOfferInstList)) {
            dtoList = CopyToDtoUtil.transOfferInstDtoList(kiteOfferInstList);
            // TODO 待确认 装箱
        }
        dtoList.removeIf(kiteOfferInst -> StrTools.isEqual(KeyConsts.ACTION_TYPE_D, kiteOfferInst.getActionType()));
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }


    /***
     * 查询可选包实例属性
     *
     * @param sceneInstId
     * @param additionalOfferInstId
     * @param custId 客户id，分片字段，必填
     * @return
     */
    @Override
    @Validated
    public DataResult<List<InstAttrDTO>> listAdditionalOfferInstAttrsByOfferInstId(@KiteNotBlank String sceneInstId,
        @KiteNotBlank String additionalOfferInstId, @KiteNotBlank String custId) {
        KiteOfferInst inst = querySceneInstService.getOfferInst(custId, additionalOfferInstId);
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        List<KiteAttr> kiteAttrList = inst.listAttrs();
        operateInstAttrService.getKiteInstAttrs(inst, kiteAttrList, sceneInst);
        List<InstAttrDTO> dtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(kiteAttrList)) {
            dtoList = CopyToDtoUtil.transInstAttrDtoList(kiteAttrList);
        }

        dtoList.stream().forEach(instAttrDTO -> { // [1694351]要求可选包订购竣工后，再进去查看时要求都不可编辑
            if (!Objects.equals(ActionType.A, inst.getActionType()) && KiteStringUtils
                .equalsAny(instAttrDTO.getFieldName(), KeyConsts.EFF_DATE, KeyConsts.EFF_DATE_TYPE, KeyConsts.EXP_DATE,
                    KeyConsts.EXP_DATE_TYPE,
                    KeyConsts.EXP_DATE_TYPE_LEN_SEL)) {      //判断是否是 生效时间类型，生效时间， 失效时间， 失效时间类型， 账期的一种
                instAttrDTO.setIsEdit("F");
            }
        });
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }

    /***
     * 获取迁转退订可选包
     *
     * @param sceneInstId
     * @param offerInstId 新的迁转套餐销售品实例标识
     * @param prodInstId 新的产品实例标识
     * @param custId 客户id，分片字段，必填
     * @return
     */
    @Override
    @Validated
    public DataResult<List<OfferInstDTO>> listUnSubscribeAdditionalOfferInst(@KiteNotBlank String sceneInstId,
        @KiteNotBlank String offerInstId, @KiteNotBlank String prodInstId, @KiteNotBlank String custId) {
        // TODO 待确认 迁转类型
        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listAdditionalOfferInstsFromProdInst(sceneInstId,
            prodInstId);
        List<OfferInstDTO> dtoList = CopyToDtoUtil.transOfferInstDtoList(kiteOfferInstList);
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }

    /***
     * 获取迁转的同转可选包
     *
     * @param sceneInstId
     * @param offerInstId 新的迁转套餐销售品实例标识
     * @param prodInstId 新的产品实例标识
     * @param custId 客户id，分片字段，必填
     * @return
     */
    @Override
    @Validated
    public DataResult<List<OfferInstDTO>> listSameMoveAdditionalOfferInst(@KiteNotBlank String sceneInstId,
        @KiteNotBlank String offerInstId, @KiteNotBlank String prodInstId, @KiteNotBlank String custId) {
        // TODO 待确认 迁转类型
        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listAdditionalOfferInstsFromProdInst(sceneInstId,
            prodInstId);
        List<OfferInstDTO> dtoList = CopyToDtoUtil.transOfferInstDtoList(kiteOfferInstList);
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }

    /**
     * 根据可选包销售品id获取套餐销售品的可选包销售品实例
     * @param custId 客户id
     * @param offerInstId 套餐销售品实例id
     * @param offerId 可选包销售品id
     * @return 可选包销售品实例列表
     */
    @Override
    public DataResult<List<OfferInstDTO>> listAdditionalOfferInstsFromMainOfferInst(String custId, String offerInstId,
        String offerId) {
        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listAdditionalOfferInstsFromMainOfferInst(custId, offerInstId, offerId);
        List<OfferInstDTO> dtoList = CopyToDtoUtil.transOfferInstDtoList(kiteOfferInstList);
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }


    /**
     * 获取套餐销售品实例/促销包销售品实例的所有可选包销售品实例
     * @param custId 客户id
     * @param offerInstId 销售品实例id(套餐销售品、促销销售品)
     * @param offerId 可选包销售品id
     * @return 可选包销售品实例列表
     */
    @Override
    public DataResult<List<OfferInstDTO>> listAdditionalOfferInstsFromOfferInst(String custId, String offerInstId, String offerId) {
        List<KiteOfferInst> kiteOfferInstList = querySceneInstService.listAdditionalOfferInstsFromOfferInst(custId, offerInstId);
        List<OfferInstDTO> dtoList = CopyToDtoUtil.transOfferInstDtoList(kiteOfferInstList.stream().filter(offerInst -> Objects.equals(offerId, offerInst.getOfferId())).collect(Collectors.toList()));
        return ErrorConsts.SUCCESS.getResult(dtoList);
    }

    @Override
    public DataResult<List<ProdInstDTO>> listAdditionalOfferMembersExclusively(String offerInstId, String custId, List<ProdInstDTO> prodInstDtos) {
        Set<String> prodInstIds = new HashSet<>();
        List<KiteProdInst> prodInsts = new LinkedList<>();
        querySceneInstService.listAdditionalOfferInstsFromOfferInst(custId, offerInstId).forEach(
            offerInst -> querySceneInstService.listProdInstsFromOfferInst(custId, offerInst.getOfferInstId()).forEach(prodInst -> {
                if (prodInstIds.add(prodInst.getProdInstId())) {
                    prodInsts.add(prodInst);
                }
            })
        );
        prodInstDtos.forEach(dto -> prodInstIds.removeIf(id -> id.equals(dto.getProdInstId())));
        prodInsts.removeIf(t -> !prodInstIds.contains(t.getProdInstId()));
        return ErrorConsts.SUCCESS.getResult(CopyToDtoUtil.transProdInstDtoListForAccess(prodInsts));
    }

    @Override
    public DataResult<List<AdditionalOfferGroupDTO>> listRelAdditionalOfferGroups(String offerId, String prodInstId, String custId) {
        KiteProdInst prodInst = querySceneInstService.getProdInst(custId, prodInstId);
        String baseOfferId = ProductCache.get(prodInst.getProdId()).getBaseOfferId();
        Set<String> additionalOfferOfProduct = OfferRelCache.get(baseOfferId).stream().map(OfferRelInfo::getzOfferId).collect(Collectors.toSet());
        List<AdditionalOfferGroupDTO> additionalOfferGroups = Lists.newArrayList();
        List<KiteOfferInst> additionalOfferInsts = querySceneInstService.listAdditionalOfferInstsByProdInstId(custId, prodInstId);
        Map<String, List<MemberRightOfferDTO>> offerGroup = queryFifthGenerationService.listMemberRightOffers(offerId).getResultObject();
        for (List<MemberRightOfferDTO> members : offerGroup.values()) {
            MemberRightOfferDTO member = members.get(0);
            AdditionalOfferGroupDTO additionalOfferGroup = new AdditionalOfferGroupDTO();
            additionalOfferGroup.setOfferGrpId(member.getOfferGrpId());
            additionalOfferGroup.setOfferGrpName(member.getOfferGrpName());
            additionalOfferGroup.setMaxValue(member.getMaxValue());
            additionalOfferGroup.setMinValue(member.getMinValue());
            additionalOfferGroup.setGroupMembers(members.stream().map(t -> memberRight2OfferDTO(t, additionalOfferOfProduct)).collect(Collectors.toList()));
            Set<String> memberOfferIds = members.stream().map(MemberRightOfferDTO::getOfferId).collect(Collectors.toSet());
            additionalOfferGroup.setAdditionalOfferInsts(additionalOfferInsts.stream()
                .filter(t -> memberOfferIds.contains(t.getOfferId())).map(CopyToDtoUtil::packageOfferInstDTO).collect(Collectors.toList()));
            additionalOfferGroups.add(additionalOfferGroup);
        }
        return ErrorConsts.SUCCESS.getResult(additionalOfferGroups);
    }

    private OfferDTO memberRight2OfferDTO(MemberRightOfferDTO memberRightOfferDTO, Set<String> additionalOfferOfProduct) {
        OfferDTO offerDTO = new OfferDTO();
        offerDTO.setOfferId(memberRightOfferDTO.getOfferId());
        offerDTO.setOfferName(memberRightOfferDTO.getOfferName());
        offerDTO.setOfferDesc(memberRightOfferDTO.getOfferDesc());
        offerDTO.setType(additionalOfferOfProduct.contains(memberRightOfferDTO.getOfferId()) ? KeyConsts.ADDITIONAL_PRODUCT_TYPE : KeyConsts.ADDITIONAL_OFFER_TYPE);
        return offerDTO;
    }

    @Override
    public DataResult<List<OfferInstDTO>> listAdditionalOfferInstsInGroup(String offerGroupId, String prodInstId, String custId) {
        Set<String> members = offerGrpMemberMapper.listMembersInGroup(offerGroupId).stream().map(OfferGrpMember::getOfferId).map(String::valueOf).collect(Collectors.toSet());
        List<OfferInstDTO> additionalOfferInsts = querySceneInstService.listAdditionalOfferInstsByProdInstId(custId, prodInstId).stream()
            .filter(t -> members.contains(t.getOfferId())).map(CopyToDtoUtil::packageOfferInstDTO2).collect(Collectors.toList());
        return ErrorConsts.SUCCESS.getResult(additionalOfferInsts);
    }

}
